package server.service.impl;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import server.config.exception.BizException;
import server.dao.*;
import server.model.entity.*;
import server.service.OrderService;
import server.service.UserBlanceService;
import server.service.UserService;
import server.tool.operLog.OperLog;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 创建人:    xvzhe
 * 创建时间:
 * 修改时间:
 * 版本:      v1.0
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    ShopOrderDao shopOrderDao;
    @Autowired
    ShopOrderItemDao shopOrderItemDao;
    @Autowired
    UsersDao usersDao;
    @Autowired
    UserService userService;
    @Autowired
    UserBlanceService userBlanceService;
    @Autowired
    FrmDictionDao frmDictionDao;
    @Autowired
    UserBlanceDao userBlanceDao;
    @Autowired
    BlanceRecordDao blanceRecordDao;
    @Autowired
    MessageDao messageDao;


    @Override
    @Transactional
    @OperLog("订单完成回调")
    public Boolean payOrder(ShopOrder shopOrder) {
        try {
            // 刷新订单状态
            shopOrder.setStatus(ShopOrder.Status.YES);
            shopOrderDao.save(shopOrder);

            if (shopOrder.getAnnul().compareTo(BigDecimal.ZERO) > 0) {
                UserBlance ub = userBlanceDao.findByTypeAndUserId(UserBlance.Type.RMB, shopOrder.getUsers().getId());
                ub.setFrostMoney(ub.getFrostMoney().subtract(shopOrder.getAnnul()));
                userBlanceDao.save(ub);
                BlanceRecord blanceRecord = new BlanceRecord();
                blanceRecord.setStatus(true);
                blanceRecord.setLog("订单抵扣（订单号："+shopOrder.getId()+"）");
                blanceRecord.setType(BlanceRecord.Type.DK);
                blanceRecord.setUType(UserBlance.Type.RMB);
                blanceRecord.setBlanceId(ub.getId());
                blanceRecord.setUserId(shopOrder.getUsers().getId());
                blanceRecord.setAfter(ub.getFrostMoney().add(shopOrder.getAnnul()));
                blanceRecord.setBefor(ub.getFrostMoney());
                blanceRecordDao.save(blanceRecord);
            }
            AtomicReference<Integer> count = new AtomicReference<>(0);
            List<ShopOrderItem> shopOrderItems = shopOrderItemDao.findByShopOrderId(shopOrder.getId());
            shopOrderItems.forEach(item->{
                BigInteger it = item.getShop().getMoney().divide(new BigDecimal(1500)).multiply(new BigDecimal(item.getCount())).toBigInteger();
                count.set(count.get()+Integer.parseInt(String.valueOf(it)));
            });
            // 计算业绩
            Users uself = shopOrder.getUsers();
            uself.setPerformance(uself.getPerformance() + count.get());
            uself.setSelfPerformance(uself.getSelfPerformance() + count.get());
            if (uself.getGrade().equals(Users.Grade.GENERAL)) {
                uself.setGrade(Users.Grade.VIP);
            }
            if (uself.getPerformance() >= 5) {
                uself.setGrade(Users.Grade.COLONEL);
            }
            usersDao.save(uself);
            // 对于父链的所有人业绩++；
            if (StringUtils.isNotBlank(uself.getTree())) {
                usersDao.updateAddByUserId(Arrays.asList(uself.getTree().split(",")), uself.getPerformance());
                // 刷新团长
                List<Users> parentList = usersDao.findByIdInOrderByTreeNumDesc(Arrays.asList(uself.getTree().split(",")));
                referCOLONEL(parentList);
                // 刷新经理
                referMANAGER(parentList);
                referMAJOR(parentList);
                referTRUSTEE(parentList);
                referCEO(parentList);
                Users up = usersDao.findById(uself.getParentId()).get();
                String log = shopOrder.getUsers().getName() + "购买" + shopOrder.getCount() + "件商品";

                // 直推奖励
                userBlanceService.insBlance(uself.getParentId(),
                        new BigDecimal(frmDictionDao.findByKeyst(up.getGrade().name()).getVal()).multiply(new BigDecimal(count.get())),
                        UserBlance.Type.RMB, BlanceRecord.Type.ONE, log);
                // 间接奖励
                if (StringUtils.isNotBlank(up.getParentId())) {
                    userBlanceService.insBlance(up.getParentId(),
                            new BigDecimal(frmDictionDao.findByKeyst("IND").getVal()).multiply(new BigDecimal(count.get())),
                            UserBlance.Type.RMB, BlanceRecord.Type.TWO, log);
                }
                fdINS(parentList.stream().filter(item -> !item.getId().equals(uself.getParentId())).collect(Collectors.toList()), count.get(),
                        log, usersDao.findById(uself.getParentId()).get().getGrade());
                Message message = new Message();
                message.setType(Message.Type.BUY);
                message.setWorkId(shopOrder.getId());
                message.setUsers(shopOrder.getUsers());
                message.setNote(log);
                messageDao.save(message);
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            new BizException("订单失败");
            return false;
        }
        return true;
    }

    // 辅导奖励
    private void fdINS(List<Users> parent, int count, String log, Users.Grade grade) {
        Users.Grade gd = grade;
        for (int i = 0; i < parent.size(); i++) {
            if (parent.get(i).getGrade().getNum() > gd.getNum()) {
                if (parent.get(i).getGrade().getNum() - gd.getNum() > 1) {
                    BigDecimal money = BigDecimal.ZERO;
                    for (int j = 0; j < parent.get(i).getGrade().getNum() - grade.getNum(); j++) {
                        money = money.add(new BigDecimal(
                                frmDictionDao.findByKeyst("F_" + Users.Grade.getNumBy(grade.getNum() + 1 + j))
                                        .getVal()).multiply(new BigDecimal(count)));
                    }
                    if (money.compareTo(BigDecimal.ZERO) > 0) {
                        userBlanceService.insBlance(parent.get(i).getId(),
                                money,
                                UserBlance.Type.RMB, BlanceRecord.Type.THREE, log);
                    }
                } else {
                    userBlanceService.insBlance(parent.get(i).getId(),
                            new BigDecimal(frmDictionDao.findByKeyst("F_" + parent.get(i).getGrade().name()).getVal()).multiply(new BigDecimal(count)),
                            UserBlance.Type.RMB, BlanceRecord.Type.THREE, log);
                }
                if (parent.get(i).getGrade().equals(Users.Grade.CEO)) {
                    break;
                }
                gd = parent.get(i).getGrade();
            }
        }
    }

    private void referCOLONEL(List<Users> parent) {
        parent.stream().filter(item -> item.getPerformance() >= 20).forEach(item -> {
            if (item.getGrade().equals(Users.Grade.GENERAL) || item.getGrade().equals(Users.Grade.VIP)) {
                item.setGrade(Users.Grade.COLONEL);
                usersDao.save(item);
            }
        });
    }

    /*
     * 刷新经理
     * @Author: xvzhe
     * @Version: 1.0
     */
    private void referMANAGER(List<Users> parent) {
        parent.stream().filter(item -> item.getPerformance() >= 70 && item.getPerformance() < 300).forEach(item -> {
            if (item.getGrade().equals(Users.Grade.GENERAL) || item.getGrade().equals(Users.Grade.VIP) || item.getGrade().equals(Users.Grade.COLONEL)) {
                int min = usersDao.findByParentId(item.getId()).stream().mapToInt(Users::getPerformance).min().getAsInt();
                if (min >= 40) {
                    item.setGrade(Users.Grade.MANAGER);
                    usersDao.save(item);
                }
            }
        });
    }

    /*
     * 刷新总监
     * @Author: xvzhe
     * @Version: 1.0
     */
    private void referMAJOR(List<Users> parent) {
        parent.stream().filter(item -> item.getPerformance() >= 300).forEach(item -> {
            if (item.getGrade().equals(Users.Grade.GENERAL) || item.getGrade().equals(Users.Grade.VIP) || item.getGrade().equals(Users.Grade.COLONEL)
                    || item.getGrade().equals(Users.Grade.MANAGER)) {
                int min = usersDao.findByParentId(item.getId()).stream().mapToInt(Users::getPerformance).min().getAsInt();
                if (min >= 200) {
                    item.setGrade(Users.Grade.MAJOR);
                    usersDao.save(item);
                }
            }
        });
    }

    private void referTRUSTEE(List<Users> parent) {
        parent.stream().forEach(item -> {
            if (item.getGrade().equals(Users.Grade.GENERAL) || item.getGrade().equals(Users.Grade.VIP) || item.getGrade().equals(Users.Grade.COLONEL)
                    || item.getGrade().equals(Users.Grade.MANAGER) || item.getGrade().equals(Users.Grade.MAJOR)) {
                List<Users> pu = usersDao.findByParentId(item.getId());
                // 经理
                AtomicInteger MANAGER = new AtomicInteger(0);
                // 总监
                AtomicInteger MAJOR = new AtomicInteger(0);
                pu.stream().forEach(it -> {
                    if (it.getGrade().equals(Users.Grade.MANAGER)) {
                        MANAGER.getAndAdd(1);
                    }
                    if (it.getGrade().equals(Users.Grade.MAJOR)) {
                        MAJOR.getAndAdd(1);
                    }
                });
                if (MAJOR.get() >= 2 && MANAGER.get() >= 3) {
                    item.setGrade(Users.Grade.TRUSTEE);
                    usersDao.save(item);
                }
            }
        });
    }

    private void referCEO(List<Users> parent) {
        parent.stream().forEach(item -> {
            if (item.getGrade().equals(Users.Grade.GENERAL) || item.getGrade().equals(Users.Grade.VIP) || item.getGrade().equals(Users.Grade.COLONEL)
                    || item.getGrade().equals(Users.Grade.MANAGER) || item.getGrade().equals(Users.Grade.MAJOR) || item.getGrade().equals(Users.Grade.TRUSTEE)) {
                List<Users> pu = usersDao.findByParentId(item.getId());
                AtomicInteger TRUSTEE = new AtomicInteger(0);
                pu.stream().forEach(it -> {
                    if (it.getGrade().equals(Users.Grade.TRUSTEE)) {
                        TRUSTEE.getAndAdd(1);
                    }
                });
                if (TRUSTEE.get() >= 2) {
                    item.setGrade(Users.Grade.CEO);
                    usersDao.save(item);
                }
            }
        });
    }
}
